package com.yycx.module.bus.provider.handler.haiying;

import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.constants.CommonConstants;
import com.yycx.common.lock.RedissonLocker;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.mybatis.query.CriteriaQuery;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.utils.DateUtils;
import com.yycx.common.utils.RedisUtils;
import com.yycx.module.admin.client.entity.BaseUser;
import com.yycx.module.admin.provider.service.BaseUserService;
import com.yycx.module.bus.client.entity.BusPayment;
import com.yycx.module.bus.client.entity.hy.HyOrder;
import com.yycx.module.bus.client.enums.AmountTypeEnum;
import com.yycx.module.bus.client.enums.HySaleTypeEnum;
import com.yycx.module.bus.provider.service.BusPaymentService;
import com.yycx.module.bus.provider.service.hy.HyOrderDetailService;
import com.yycx.module.bus.provider.service.hy.HyOrderService;
import com.yycx.module.bus.provider.service.hy.HyRemoteOrderService;
import com.yycx.module.system.client.entity.SysCompany;
import com.yycx.module.system.provider.service.SysCompanyService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

@Component
@Slf4j
public class BusinessUtils {
    @Autowired
    private SysCompanyService companyService;

    @Autowired
    private BusPaymentService paymentService;

    @Autowired
    private BaseUserService baseUserService;

    @Autowired
    private HyOrderService orderService;

    @Autowired
    public RedissonLocker redisLock;

    @Autowired
    private HyRemoteOrderService hyRemoteOrderService;


    @Resource
    private HyOrderDetailService orderDetailService;

    @Resource
    private RedisUtils redisUtils;

    /**
     * 按用户开始生成订单号
     */
    public String getPaymentNo(Long companyId, Long userId, AmountTypeEnum amountTypeEnum) {
        BaseUser baseUser = baseUserService.getById(userId);
        SysCompany company = companyService.getById(companyId);
        String companyNo = company.getCompanyNo();
        String userNo = companyNo + FlymeUtils.getString(baseUser.getUserNo(), "").replace("SBL", "");
        //加锁避免重复
        RLock lock = redisLock.lock(userId);
        String result = null;
        try {
            CriteriaQuery<BusPayment> cq = new CriteriaQuery(BusPayment.class);
            cq.select("paymentNo");
            cq.eq(true, "companyId", companyId);
            if (FlymeUtils.isNotEmpty(amountTypeEnum)) {
                userNo = amountTypeEnum.getPrefix() + userNo;
            }
            cq.likeRight(true, "paymentNo", userNo);
            if (FlymeUtils.isNotEmpty(amountTypeEnum)) {
                cq.eq(true, "amountType", amountTypeEnum.getCode());
            }
            cq.orderByDesc("createTime", "paymentNo");
            cq.limit(1);
            BusPayment payment = paymentService.getOne(cq, false);
            if (FlymeUtils.isEmpty(payment)) {
                return userNo + "0000001";
            }
            String lastOrderNo = payment.getPaymentNo().substring(8);
            result = userNo + String.format("%07d", Long.parseLong(lastOrderNo) + 1);
        } finally {
            redisLock.unlock(lock);
        }
        return result;
    }

    /**
     * 按用户开始生成订单号
     */
    public String getPaymentNo(Long companyId, Long userId) {
        BaseUser baseUser = baseUserService.getById(userId);
        SysCompany company = companyService.getById(companyId);
        String companyNo = company.getCompanyNo();
        String userNo = companyNo + FlymeUtils.getString(baseUser.getUserNo(), "").replace("SBL", "");
        //加锁避免重复
        RLock lock = redisLock.lock(userId);
        String result = null;
        try {
            CriteriaQuery<BusPayment> cq = new CriteriaQuery(BusPayment.class);
            cq.select("paymentNo");
            cq.eq(true, "companyId", companyId);
            cq.likeRight(true, "paymentNo", userNo);
            cq.orderByDesc("createTime", "paymentNo");
            cq.limit(1);
            BusPayment payment = paymentService.getOne(cq, false);
            if (FlymeUtils.isEmpty(payment)) {
                return userNo + "0000001";
            }
            String lastOrderNo = payment.getPaymentNo().substring(6);
            result = userNo + String.format("%07d", Long.parseLong(lastOrderNo) + 1);
        } finally {
            redisLock.unlock(lock);
        }
        return result;
    }

    /**
     * 按月从001开始生成序列号
     */
    public String getOrderNo(SysCompany company, BaseUser baseUser) {
        Long companyId = company.getCompanyId();
        String dbName = company.getCompanyErpInstance();
        EntityMap orderConfig = getOrderConfig(dbName, baseUser);
        String sysid = orderConfig.get("sysid");
        String companyNo = FlymeUtils.getString(company.getCompanyNo(), "01");
        sysid += companyNo;
        Long userId = baseUser.getUserId();
        //加锁避免重复
        RLock lock = redisLock.lock(userId);
        String result = null;
        try {
            CriteriaQuery<HyOrder> cq = new CriteriaQuery(HyOrder.class);
            cq.select("orderId", "orderNo");
            cq.eq(true, "companyId", companyId);
            cq.likeRight(true, "orderNo", sysid);
            cq.orderByDesc("createTime", "orderNo");
            cq.limit(1);
            HyOrder hyOrder = orderService.getOne(cq);
            if (FlymeUtils.isEmpty(hyOrder)) {
                return sysid + "000001";
            }
            String lastOrderNo = hyOrder.getOrderNo();
            if (lastOrderNo.startsWith("0")) {
                lastOrderNo = lastOrderNo.substring(6);
            }
            result = sysid + String.format("%08d", Long.parseLong(lastOrderNo) + 1);
        } finally {
            redisLock.unlock(lock);
        }
        return result;
    }

    /**
     * 生成订单ID
     */
    private EntityMap getOrderConfig(String dbName, BaseUser baseUser) {
        EntityMap result = new EntityMap();
        ApiAssert.isNotEmpty("数据库实例未配置", dbName);
        String hostName = baseUser.getHostName();
        if(FlymeUtils.isNotEmpty(hostName)){
            ApiAssert.isNotEmpty("主机名未配置", hostName);
            EntityMap sysProperties = hyRemoteOrderService.selectSysProperties(dbName, hostName);
            //ApiAssert.isNotEmpty("站点配置不存在", sysProperties);
            if(FlymeUtils.isNotEmpty(sysProperties)){
                //站点编号
                String sysid = sysProperties.get("sysid");
                result.put("sysid", sysid);
            }else{
                result.put("sysid", "50001");
            }
        }else{
            result.put("sysid", "50001");
        }
        result.put("dbName", dbName);
        return result;
    }

    /**
     * 删除海鹰订单
     *
     * @return
     */
    public ResultBody removeRemoteOrder(HyOrder order) {
        Long companyId = order.getCompanyId();
        SysCompany company = companyService.getById(companyId);
        String dbName = company.getBusinessScope();
        ApiAssert.isNotEmpty("账套实例未配置", dbName);
        String businessKey = order.getOrderId();
        Integer sourceType = order.getSourceType();
        Integer orderState = order.getOrderState();
        //是否出库
        Integer count = hyRemoteOrderService.countByOrderId(dbName, businessKey);
        //必须是结算系统录入的才能删除海鹰定单信息
        if (count.equals(0) && sourceType.equals(2)) {
            //查询库存占用信息
            List<EntityMap> orderDrugLotNums = orderDetailService.totalDrugLotNum(businessKey);
            //更新库存
            for (EntityMap orderDetails : orderDrugLotNums) {
                EntityMap params = new EntityMap();
                //库存编码
                Integer drugLotId = orderDetails.get("drugLotId");
                //商品编码
                String drugNo = orderDetails.get("drugNo");
                //该批号的总销量
                BigDecimal saleNum = orderDetails.getBigDecimal("saleNum");
                //根据库存编码查询库存信息
                EntityMap drugLotMap = hyRemoteOrderService.selectByDrugLotId(dbName, drugLotId);
                ApiAssert.isNotEmpty("未找到库存信息", drugLotMap);
                //当前在单数
                BigDecimal onUseCount = drugLotMap.getBigDecimal("onUseCount");
                //当前在单数-已售数量
                BigDecimal newOnUserCount = onUseCount.subtract(saleNum);
                if (FlymeUtils.ltzero(newOnUserCount)) {
                    log.error("###########################在单数计算错误,商品编号:" + drugNo);
                    return ResultBody.failed("在单数计算错误,禁止撤销");
                } else {
                    params.put("onUseCount", newOnUserCount);
                    params.put("drugLotId", drugLotId);
                    params.put("saleNum", saleNum.multiply(new BigDecimal("-1")));
                    //更新库存在单数
                    hyRemoteOrderService.updateByDrugLotId(dbName, params);
                    params.put("sendDate", order.getSendDate());
                    params.put("drugNo", drugNo);
                    //更新商品目录在单数
                    hyRemoteOrderService.updateLastSaleDate(dbName, params);
                }
            }
            if (orderState.equals(2)) {
                //删除订单信息
                hyRemoteOrderService.deleteOrderByOrderId(dbName, businessKey);
                hyRemoteOrderService.deleteOrderDetailsByOrderId(dbName, businessKey);
            }
            return ResultBody.ok();
        } else {
            return ResultBody.failed("订单已提单禁止撤销");
        }
    }

    @DSTransactional
    public Boolean syncUseNum(HyOrder order) {
        Integer syncTag = FlymeUtils.getInteger(order.getSyncTag(), 0);
        Integer sendState = FlymeUtils.getInteger(order.getSendState(), 0);
        String businessKey = order.getOrderId();
        Long companyId = order.getCompanyId();
        //未同步且发货
        if (syncTag.equals(0) && sendState.equals(0)) {
            //同步订单到海鹰系统出订单主,出订单细表中 更新海鹰系统商品库存 在单数，可开票数
            List<EntityMap> orderDetailsList = orderDetailService.selectByOrderId(businessKey, HySaleTypeEnum.CHA);
            ApiAssert.isNotEmpty("订单商品未添加", orderDetailsList);
            if (FlymeUtils.isNotEmpty(orderDetailsList)) {
                SysCompany company = companyService.getById(companyId.toString());
                String dbName = company.getBusinessScope();
                ApiAssert.isNotEmpty("账套实例未配置", dbName);
                List<EntityMap> orderDrugLotNums = orderDetailService.totalDrugLotNum(businessKey);
                //更新库存
                for (EntityMap orderDetails : orderDrugLotNums) {
                    EntityMap params = new EntityMap();
                    //库存编码
                    Integer drugLotId = orderDetails.get("drugLotId");
                    String drugNo = orderDetails.get("drugNo");
                    params.put("drugLotId", drugLotId);
                    //该批号的总销量
                    BigDecimal saleNum = orderDetails.getBigDecimal("saleNum");
                    params.put("saleNum", saleNum);
                    //根据库存编码查询库存信息
                    EntityMap drugLotMap = hyRemoteOrderService.selectByDrugLotId(dbName, drugLotId);
                    ApiAssert.isNotEmpty("未找到库存信息", drugLotMap);
                    //现存数量
                    BigDecimal drugCount = drugLotMap.getBigDecimal("drugCount");
                    //在单数
                    BigDecimal onUseCount = drugLotMap.getBigDecimal("onUseCount");
                    //锁定数
                    BigDecimal lockCount = drugLotMap.getBigDecimal("lockCount");
                    try {
                        //现存数量-销售数量-在单数-锁定数 结果不小于零代表库存充足
                        BigDecimal checkNum = drugCount.subtract(saleNum).subtract(onUseCount).subtract(lockCount);
                        ApiAssert.gezero("库存不足", checkNum);
                        hyRemoteOrderService.updateByDrugLotId(dbName, params);
                        params.put("sendDate", order.getSendDate());
                        params.put("drugNo", drugNo);
                        hyRemoteOrderService.updateLastSaleDate(dbName, params);
                    } catch (Exception ex) {
                        log.error("#################库存异常#############商品编号:" + drugNo + ":库存编号" + drugLotId);
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }

    /**
     * 获取海鹰数据库实例名称
     * @param companyId
     * @return
     */
    public String getDbName(Long companyId) {
        String companyErpInstance = redisUtils.getString("DBNAME:" + companyId);
        if (FlymeUtils.isEmpty(companyErpInstance)) {
            SysCompany company = companyService.getById(companyId);
            companyErpInstance = company.getCompanyErpInstance();
            redisUtils.set("DBNAME:" + companyId, companyErpInstance);
        }
        return companyErpInstance;
    }


}
